unit SynHighlighterDlg;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, SynEditActions, StdCtrls, SynEdit, ExtCtrls, SynEditHighlighter,
  SynUniHighlighter, SynUniClasses, SynUniRules;

type
  TAttrRec = record
    Fore, Back : TColor;
    FontStyle : TFontStyles;
    Attr : TSynHighlighterAttributes;
  end;

  TCustomHLDlg = class(TForm)
    Label1: TLabel;
    ComboBox1: TComboBox;
    Label2: TLabel;
    ComboBox2: TComboBox;
    GroupBox1: TGroupBox;
    CheckBox1: TCheckBox;
    CheckBox2: TCheckBox;
    CheckBox3: TCheckBox;
    ColorBox1: TColorBox;
    ColorBox2: TColorBox;
    Label3: TLabel;
    Label4: TLabel;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Panel1: TPanel;
    Image1: TImage;
    Label5: TLabel;
    SynEdit1: TSynEdit;
    procedure FormCreate(Sender: TObject);
    procedure ComboBox1Change(Sender: TObject);
    procedure ComboBox2Change(Sender: TObject);
    procedure CheckBox1Click(Sender: TObject);
    procedure CheckBox2Click(Sender: TObject);
    procedure CheckBox3Click(Sender: TObject);
    procedure ColorBox1Change(Sender: TObject);
    procedure ColorBox2Change(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button3Click(Sender: TObject);
    procedure SynEdit1StatusChange(Sender: TObject;
      Changes: TSynStatusChanges);
    procedure Button2Click(Sender: TObject);
  private
    CurrAttrs : array of TAttrRec;
    FSaved : Boolean;
  end;

var
  CustomHLDlg: TCustomHLDlg;

implementation

{$R *.dfm}

procedure TCustomHLDlg.CheckBox1Click(Sender: TObject);
begin
  if Combobox2.ItemIndex >= 0 then
  begin
    with TSynHighlighterAttributes(Combobox2.Items.Objects[Combobox2.ItemIndex]) do
      if checkbox1.Checked then
        style := style+[fsBold] else
        style := style-[fsBold];
    SynEdit1.Invalidate;
  end;
end;

procedure TCustomHLDlg.CheckBox2Click(Sender: TObject);
begin
  if Combobox2.ItemIndex >= 0 then
  begin
    with TSynHighlighterAttributes(Combobox2.Items.Objects[Combobox2.ItemIndex]) do
      if checkbox2.Checked then
        style := style+[fsUnderline] else
        style := style-[fsUnderline];
    SynEdit1.Invalidate;
  end;
end;

procedure TCustomHLDlg.CheckBox3Click(Sender: TObject);
begin
  if Combobox2.ItemIndex >= 0 then
  begin
    with TSynHighlighterAttributes(Combobox2.Items.Objects[Combobox2.ItemIndex]) do
     if checkbox3.Checked then
       style := style+[fsItalic] else
       style := style-[fsItalic];
    SynEdit1.Invalidate;
  end;
end;

procedure TCustomHLDlg.ColorBox1Change(Sender: TObject);
begin
  if Combobox2.ItemIndex >= 0 then
  begin
    with TSynHighlighterAttributes(Combobox2.Items.Objects[Combobox2.ItemIndex]) do
      Foreground := colorbox1.Selected;
    SynEdit1.Invalidate;
  end;
end;

procedure TCustomHLDlg.ColorBox2Change(Sender: TObject);
begin
  if Combobox2.ItemIndex >= 0 then
  begin
    with TSynHighlighterAttributes(Combobox2.Items.Objects[Combobox2.ItemIndex]) do
      background := colorbox2.Selected;
    SynEdit1.Invalidate;
  end;
end;

procedure TCustomHLDlg.ComboBox1Change(Sender: TObject);
var
  HL :TSynCustomHighlighter;
  procedure GetRanges(Range : TSynRange);
  var
    i : integer;
  begin
    ComboBox2.Items.AddObject(Range.ValidAttribs.Name, Range.ValidAttribs);
    for I := 0 to Range.KeyListCount - 1 do
      Combobox2.Items.AddObject(Range.KeyLists[I].ValidAttribs.Name,
      Range.KeyLists[I].ValidAttribs);
    for I := 0 to Range.SetCount - 1 do
      Combobox2.Items.AddObject(Range.Sets[I].ValidAttribs.Name,
      Range.Sets[I].ValidAttribs);
    for i := 0 to Range.RangeCount - 1 do
      GetRanges(Range.Ranges[i]);
  end;
var
  I : integer;
begin
  if not FSaved then Button3Click(nil);
  FSaved := False;
  combobox2.Clear;

  HL := TSynCustomHighlighter(Combobox1.Items.Objects[Combobox1.ItemIndex]);
  Manager.Highlighters.Items[Combobox1.ItemIndex].Load;

  if HL is TSynUniSyn then
  begin
    TSynUniSyn(HL).Prepare;
    GetRanges(TSynUniSyn(HL).MainRules)
  end else for i := 0 to HL.AttrCount - 1 do
    Combobox2.Items.AddObject(HL.Attribute[i].Name, HL.Attribute[i]);

  SetLength(CurrAttrs, ComboBox2.Items.Count);
  for i := 0 to ComboBox2.Items.Count - 1 do
  begin
    CurrAttrs[i].Attr := TSynHighlighterAttributes(Combobox2.Items.Objects[i]);
    CurrAttrs[i].Fore := CurrAttrs[i].Attr.Foreground;
    CurrAttrs[i].Back := CurrAttrs[i].Attr.Background;
    CurrAttrs[i].FontStyle := CurrAttrs[i].Attr.Style;
  end;

  ComboBox2.ItemIndex := 0;
  ComboBox2Change(nil);

  synedit1.Highlighter := HL;
  synedit1.Text := HL.SampleSource;
end;

procedure TCustomHLDlg.ComboBox2Change(Sender: TObject);
var
  Attr :  TSynHighlighterAttributes;
begin
  if Combobox2.ItemIndex >= 0 then
  begin
    Attr := TSynHighlighterAttributes(Combobox2.Items.Objects[Combobox2.ItemIndex]);
    with Attr do
    begin
      Colorbox1.Selected := Foreground;
      Colorbox2.Selected := Background;
      checkbox1.Checked := fsBold in style;
      checkbox2.Checked := fsUnderline in style;
      checkbox3.Checked := fsItalic in style;
    end;
  end;
end;

procedure TCustomHLDlg.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  action := caFree;
  if not FSaved then
    Button3Click(nil);
end;

procedure TCustomHLDlg.FormCreate(Sender: TObject);
var
  i : integer;
begin
  for i := 0 to Manager.Highlighters.Count - 1 do
    with Manager.Highlighters do
      Combobox1.Items.AddObject(Highlighters[i].LanguageName, Highlighters[i]);
  ComboBox1.ItemIndex := 0;
  ComboBox1Change(nil);
end;

procedure TCustomHLDlg.Button3Click(Sender: TObject);
var
  I : integer;
begin
  for i := Low(CurrAttrs) to High(CurrAttrs) do
  begin
    CurrAttrs[i].Attr.Foreground := CurrAttrs[i].Fore;
    CurrAttrs[i].Attr.Background := CurrAttrs[i].Back;
    CurrAttrs[i].Attr.Style := CurrAttrs[i].FontStyle;
  end;
  SynEdit1.Invalidate;
end;

procedure TCustomHLDlg.SynEdit1StatusChange(Sender: TObject;
  Changes: TSynStatusChanges);
var
  Token : string;
  Attr : TSynHighlighterAttributes;
begin
  synedit1.GetHighlighterAttriAtRowCol(synedit1.CaretXY, Token, Attr);
  if Assigned( Attr) then
  begin
    ComboBox2.ItemIndex := ComboBox2.Items.IndexOf(Attr.Name);
    ComboBox2Change(nil);
  end;
end;
procedure TCustomHLDlg.Button2Click(Sender: TObject);
begin
  FSaved := true;
end;

end.
